@file:Suppress("EXPERIMENTAL_API_USAGE")

package org.glavo.bot

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.newSingleThreadContext
import org.glavo.bot.data.Config
import java.util.concurrent.TimeUnit

sealed interface IPMIResult {
    object TimeOut : IPMIResult
    data class Failed(val message: String) : IPMIResult
    data class Success(val message: String) : IPMIResult
}

private val ipmiContext = newSingleThreadContext("ipmi")

suspend fun ipmi(command: List<String>): IPMIResult {
    val commands = (listOf(
        "ipmitool",
        "-H", Config.IPMIAddress,
        "-I", "lanplus",
        "-U", Config.IPMIUserName,
        "-P", Config.IPMIUserPassword
    ) + command).toTypedArray()

    return GlobalScope.async (ipmiContext) {
        runCatching<IPMIResult> {
            val process = Runtime.getRuntime().exec(commands)
            if (!process.waitFor(60, TimeUnit.SECONDS)) {
                process.destroy()
                return@runCatching IPMIResult.TimeOut
            }

            var res = process.inputStream.bufferedReader().use { it.readText() }
            if (res.isNotEmpty()) {
                res = res.trim()
                if (command.firstOrNull() == "power") {
                    when (res) {
                        "Chassis Power is off" -> res = "NAS 处于关闭状态"
                        "Chassis Power is on" -> res = "NAS 处于开启状态"
                        "Chassis Power Control: Soft" -> res = "NAS 关机中"
                        "Chassis Power Control: Up/On" -> res = "已打开 NAS 电源"
                        "Chassis Power Control: Down/Off" -> res = "已关闭 NAS 电源"
                        "Chassis Power Control: Reset", "Chassis Power Control: Cycle" -> res = "正在重启 NAS"
                    }
                }

                return@runCatching IPMIResult.Success(res)
            }

            res = process.errorStream.bufferedReader().use { it.readText() }.trim()

            when (res) {
                "Error: Unable to establish IPMI v2 / RMCP+ session" -> res = "无法连接 NAS，可能设备已离线"
            }

            return@runCatching IPMIResult.Failed(res)
        }
    }.await().getOrThrow()
}